package com.dru.drutils.web;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Set;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;

import android.util.Log;

public class WebUtils {

	private static String cookie = null;
	
	/**
	 * 
	 * @param absoluteFilePaths array of Strings specifying the absolute file
	 * path of each file on the system to upload
	 * @param serverURL the String url of the server where the files and data
	 * are to be uploaded
	 * @param postData any data in the form of String Key-Value pairs to be 
	 * HTTPPOST'ed to the server, as a HashMap
	 * @return the output of the server after receiving the files and data
	 */
	public static String multipartPostFiles( String[] absoluteFilePaths, String serverURL, HashMap<String, String> postData )
	{
		if ( serverURL == null || serverURL.equals( "" ) )
		{
			return "ERROR: server url passed to multipartPostFiles() was blank";
		}
		
		HttpURLConnection connection = null;
		DataOutputStream outputStream = null;

		String urlServer = serverURL;
		String lineEnd = "\r\n";
		String twoHyphens = "--";
		String boundary =  "*****";
		String serverResponseMessage = "SERVER SAYS NOTHING";

		
		int bytesRead, bytesAvailable, bufferSize;
		byte[] buffer;
		int maxBufferSize = 4*1024*1024;

		try
		{
			URL url = new URL(urlServer);
			connection = (HttpURLConnection) url.openConnection();

			// Allow Inputs & Outputs
			connection.setDoInput(true);
			connection.setDoOutput(true);
			connection.setUseCaches(false);

			// Enable POST method
			connection.setRequestMethod("POST");

			connection.setRequestProperty("Connection", "Keep-Alive");
			connection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
			
			outputStream = new DataOutputStream( connection.getOutputStream() );

			// write POST data (pulseType, pulseUserUID, etc.), if there is any
			if ( postData != null )
			{
				Set<String> keySet = postData.keySet();

				Object[] keyArray = keySet.toArray();
				
				for (int i = 0; i < keyArray.length; i++ )
				{	
					
					if ( postData.get( keyArray[i] ) != null )
					{
						outputStream.writeBytes(twoHyphens + boundary + lineEnd);
						outputStream.writeBytes("Content-Disposition: form-data; name=\"" + (String)keyArray[i] + "\""+ lineEnd);
						outputStream.writeBytes(lineEnd);
						outputStream.writeBytes( postData.get( keyArray[i] ) );
						outputStream.writeBytes(lineEnd);
						outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
					}
					
				}
				
			}

			
			// posting file data (thumbnail and media), if there is any
			for ( int i = 0; i < absoluteFilePaths.length; i++ )
			{
				if ( absoluteFilePaths[i] != null && !absoluteFilePaths[i].equals( "" ) )
				{
					outputStream.writeBytes(twoHyphens + boundary + lineEnd);
					outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + absoluteFilePaths +"\"" + lineEnd);
					outputStream.writeBytes(lineEnd);
	
					FileInputStream fileInputStream = new FileInputStream(new File( absoluteFilePaths[i] ) );
					bytesAvailable = fileInputStream.available();
					bufferSize = Math.min(bytesAvailable, maxBufferSize);
					buffer = new byte[bufferSize];
	
					// Read file
					bytesRead = fileInputStream.read(buffer, 0, bufferSize);
	
					while (bytesRead > 0) {
						outputStream.write(buffer, 0, bufferSize);
						bytesAvailable = fileInputStream.available();
						bufferSize = Math.min(bytesAvailable, maxBufferSize);
						bytesRead = fileInputStream.read(buffer, 0, bufferSize);
					}
					
					fileInputStream.close();
				}
			}

			outputStream.writeBytes(lineEnd);
			outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
			
			serverResponseMessage = convertStreamToString( connection.getInputStream() );
			
			outputStream.flush();
			outputStream.close();
			connection.getInputStream().close();
			
			Log.d("Server Response", serverResponseMessage);
		}
		catch (Exception ex)
		{
			Log.d("Send File to Server", "failed to send: "+ex.getMessage());
		}
		
		return serverResponseMessage;
	}
	
	/**
	 * 
	 * @param is input stream ( such as the input or response from an httpurlconnection )
	 *  to convert to a string.
	 * @return the string representation of the stream
	 */
	public static String convertStreamToString( InputStream is )
	{
		BufferedReader	reader	= new BufferedReader( new InputStreamReader( is ), 8 * 1024 );
		StringBuilder	sb		= new StringBuilder();
		String			line	= null;
		
        try
        {
        	while( ( line = reader.readLine() ) != null )
        	{
        		sb.append( line + "\n" );
        	}
        }
        catch( IOException e )
        {
        	e.printStackTrace();
        }
        finally
        {
        	try
        	{
        		is.close();
        	}
        	catch( IOException e )
        	{
        		e.printStackTrace();
        	}
        }
        
        return sb.toString();
	}
	
	/**
	 * credit: TSGJSON class
	 * @param url
	 * @return
	 */
	public static JSONObject getURLasJSON( String url )
	{
		JSONObject			jsonResponse	= null;
		DefaultHttpClient	httpClient		= null;
		HttpGet				httpGet			= null;
		HttpResponse		httpResponse	= null;
		
		try
		{
			httpClient		= new DefaultHttpClient();
			httpGet			= new HttpGet( url );
			
			httpGet.setHeader( "Accept", "application/json" );
			httpGet.setHeader( "Content-type", "application/json" );
			
			httpResponse = httpClient.execute( httpGet );
			
			jsonResponse = new JSONObject( convertStreamToString( httpResponse.getEntity().getContent() ) );
		}
		catch( Exception e )
		{
			System.out.println( e.getLocalizedMessage() );
		}
		
		return jsonResponse;
	}
	
	public static String getURLasJSONString( String url )
	{
		String				jsonResponse	= null;
		DefaultHttpClient	httpClient		= null;
		HttpGet				httpGet			= null;
		HttpResponse		httpResponse	= null;
		
		try
		{
			httpClient		= new DefaultHttpClient();
			httpGet			= new HttpGet( url );
			
			httpGet.setHeader( "Accept", "application/json" );
			httpGet.setHeader( "Content-type", "application/json" );
			
			if ( WebUtils.cookie != null )
			{
				httpGet.setHeader( "Cookie", WebUtils.cookie );
			}
			
			httpResponse = httpClient.execute( httpGet );
			
			jsonResponse = convertStreamToString( httpResponse.getEntity().getContent() );
		}
		catch( Exception e )
		{
			System.out.println( e.getLocalizedMessage() );
		}
		
		return jsonResponse;
	}
	
	public static String postJSONToURL( String urlString, String json )
	{
		String reply = null;
		byte[] postData = json.getBytes();
		URL url = null;
	    try {
		    url = new URL( urlString );
		    URLConnection connection = null;
		    connection = url.openConnection();
		    HttpURLConnection httppost = (HttpURLConnection) connection;
		    httppost.setDoInput(true);
		    httppost.setDoOutput(true);
		    httppost.setRequestMethod("POST");
		    httppost.setRequestProperty("User-Agent", "TextToGetHer");
		    httppost.setRequestProperty("Accept_Language", "en-US");
		    httppost.setRequestProperty("Content-Type", "application/json");
		    httppost.setRequestProperty("Accept", "application/json");
		    DataOutputStream dos = new DataOutputStream( httppost.getOutputStream() );
		    dos.write( postData ); // bytes[] of post data
		    
		    reply = convertStreamToString( httppost.getInputStream() );
		    
		    try 
		    {
		    	WebUtils.cookie = connection.getHeaderField( "Set-Cookie" );
		    }
		    catch ( Exception e)
		    {
		    	Log.d( "WebUtils", "failed reading cookie");
		    }
	    }
	    catch (Exception e)
	    {
	    	Log.d("WebUtils POST fail", e.getMessage());
	    }
	    return reply;
	}
}
	
